#!/bin/bash
#
# clandestine.googlecode.com
#
set -eu # be strict

TEST=what?
declare -ri TEST
declare -p TEST
echo $TEST
exit 0


PATH="/usr/local/bin:/usr/bin:/bin"
readonly VERSION="ashes"


readonly DN_PRFX="/var/lib/mldonkey"
readonly FN_SOURCE="/dev/zero"
readonly FN_THRESHOLD=".max"
declare -ri DEF_THRESHOLD=1500
readonly MLC_BIN="mldonkey_command"
readonly MLC_HOST="localhost"
declare -ri MLC_PORT=4000
readonly MLC_USER="user"
readonly MLC_PASW="user"
readonly FN_LOG="$DN_PRFX/mldwd.log"
readonly DN_TORRENTS_SEED="$DN_PRFX/torrents/seeded"
readonly DN_TORRENTS_DOWN="$DN_PRFX/torrents/downloads"
readonly DN_INCOMING_DIRS="$DN_PRFX/incoming/directories"
readonly DN_INCOMING_FILES="$DN_PRFX/incoming/files"
readonly DN_COMMIT="$DN_PRFX/incoming/commited"
readonly DN_COUNTERS="$DN_PRFX/mldwd.d"

function Log () {
	echo "`date` $@" >> "$FN_LOG"
}

function SizeOf () {
	if [[ -e "$1" ]]; then stat --format=%s "$1"; else echo "${2-0}"; fi
}

function MLD () {
	[[ "$1" ]] || return 0
	if which "$MLC_BIN" &> /dev/null; then
		"$MLC_BIN" -P "$MLC_PORT" -h "$MLC_HOST" -u "$MLC_USER" -p "$MLC_PASW" "$@"
	else
		Log "no '$MLC_BIN' executable found in path $PATH"
	fi
}

function Add () {
	[[ "$2" ]] || return 1
	local -i DIFF  SIZE=$(( $2 + 0 ))
	local DIR="$DN_COUNTERS/$1"  LAST=""
	[[ -e "$DIR" ]] || { mkdir --parents "$DIR"; Log "created directory $DIR"; }
	[[ -d "$DIR" ]] && touch --no-create --time=mtime "$DIR"
	[[ $SIZE -gt 0 ]] || return 0
	LAST=`ls -1 "$DIR" | sort --numeric-sort | tail -n 1`
	if ! [[ -e "$DIR/$LAST" && `SizeOf "$DIR/$LAST"` -le $SIZE ]]; then LAST=$(( $LAST + 1 )); fi
	DIFF=$(( $SIZE - `SizeOf "$DIR/$LAST"` ))
	head --bytes="$DIFF" "$FN_SOURCE" >> "$DIR/$LAST"
}

function Aggregate () {
	[[ "$1" ]] || return 1
	echo $(( `find "$DN_COUNTERS/$1" -maxdepth 1 -name "[0-9]*" -type f -printf "%s + "` 0 ))
}

function CommitTorrent () {
	[[ "$1" ]] || return 1
	local  SRC=""  DST=""
	[[ -r "$DN_INCOMING_FILES/$1" ]] && SRC="$DN_INCOMING_FILES/$1"
	[[ -r "$DN_INCOMING_DIRS/$1" ]] && SRC="$DN_INCOMING_DIRS/$1"
	[[ -e "$DN_COMMIT" ]] || { mkdir --parents "$DN_COMMIT"; Log "created directory $DN_COMMIT"; }
	DST="$DN_COMMIT/$1"
	while [[ -e "$DST" ]]; do DST="${DST}${RANDOM:0:1}"; done
	mv "$SRC" "$DST"
	MLD "reshare" "reshare_torrents" &> /dev/null
	Log "commited '$1' to $DN_COMMIT"
}

function Remove () {
	[[ "$1" ]] || return 1
	[[ -d "$DN_COUNTERS/$1" ]] || return 1
	if rm -r "$DN_COUNTERS/$1"; then
		Log "removed counters for $1"
	else
		Log "FAIL removing counters for $1"
	fi
}

function FetchStats () {
	local OFS="$IFS"  LINE=""  LINES=()  AMOUNT=""  TORRENT=""  MAX=""
	IFS=$'\n'
	for LINE in `MLD "set max_name_len 50000" "upstats" | head --lines=-7 | tail --lines=+6 | awk -F '|' -- '{print $3 $4}'`; do LINES+=("$LINE"); done
	IFS="$OFS"
	for LINE in "${LINES[@]}"; do
		read AMOUNT TORRENT <<< "$LINE"
		AMOUNT="${AMOUNT%%%}"
		AMOUNT="${AMOUNT//./}"
		AMOUNT="${AMOUNT##0}"
		if [[ -r "$DN_TORRENTS_DOWN/$TORRENT.torrent" ]]; then
			Add "$TORRENT" "$AMOUNT"
			continue
		fi
		if [[ -r "$DN_TORRENTS_SEED/$TORRENT.torrent" ]]; then
			Add "$TORRENT" "$AMOUNT"
			MAX=`SizeOf "$DN_COUNTERS/$TORRENT/$MAX" $DEFMAX`
			[[ "$MAX" -gt 0 && `Aggregate "$TORRENT"` -ge "$MAX" ]] && CommitTorrent "$TORRENT"
		fi
	done
}

case "$1" in
	"stats")
		for DIR in "$DN_COUNTERS"/*; do
			DIR="`basename "$DIR"`"
			AMOUNT=`Aggregate "$DIR"`
			printf "%6i: %s\n" "$AMOUNT" "$DIR"
		done
	;;
	"torrents") FetchStats;;
	"purge")
		find "$DN_COUNTERS/" -mindepth 1 -maxdepth 1 -type d -mmin +60 | while read DIR; do
			Log "purging counters for $DIR"
			rm -r "$DIR"
		done
	;;
	*) echo "mldwd $VERSION syntax: $(basename $0) { stats | torrents | purge }";;
esac
exit 0
